iT邦幫忙

2023 iThome 鐵人賽

DAY 29
0

全端 LLM 應用開發-Day29-Langchain 的 chain

我們目前已經過用了 ConversationalRetrievalChain,但是 Langchain 還有其他很多的 chain。我們今天就來介紹幾個常用的 chain,以及重要的觀念。

Chain 允許我們將多個元件組合在一起,創建一個單一、連貫的應用。我們之前就創建一個 chain,將用戶輸入與 PromptTemplate 格式化,然後將格式化的回應傳遞給 LLM。我們可以組合多個 chain 或將 chain 與其他元件組合在一起來建構出更複雜的 chains。

舉例來說,我們一直在用 ConversationalRetrievalChain ,可以加上一個參數 condense_question_llm,串接上另一個 LLM。請參考下面的程式碼:

qa = ConversationalRetrievalChain.from_llm(
    llm=AzureChatOpenAI(temperature=0, model="gpt-4"),
	retriever=doc_store.as_retriever(),
    condense_question_llm = AzureChatOpenAI(temperature=0, model='gpt-3.5-turbo'),
)

在這個範例中 condense_question_llm 放入比較便宜的模型,會把對話紀錄和問題壓縮成一個問題,再做向量搜尋。搜尋到答案後,再用貴的模型,生成高品質的答案。

LLMChain

這個是 Chain 的最基本型,我們馬上來操作看看。

建立一個 python 檔叫 chains.py,貼上以下的程式碼。


from langchain.chat_models.azure_openai import AzureChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.chains import LLMChain

OPENAI_API_KEY = "yourkey"
OPENAI_DEPLOYMENT_NAME = "gpt-35-16k"
MODEL_NAME = "gpt-35-turbo-16k"
OPENAI_DEPLOYMENT_ENDPOINT = "https://japanopenai2023ironman.openai.azure.com/"
OPENAI_API_TYPE = "azure"
OPENAI_API_VERSION = "2023-03-15-preview"


def get_llm_chain(prompt):

    llm = AzureChatOpenAI(
        openai_api_key=OPENAI_API_KEY,
        openai_api_base=OPENAI_DEPLOYMENT_ENDPOINT,
        openai_api_type=OPENAI_API_TYPE,
        openai_api_version=OPENAI_API_VERSION,
        deployment_name=OPENAI_DEPLOYMENT_NAME,
        model_name=MODEL_NAME,
        temperature=0
    )
    chain = LLMChain(llm=llm, prompt=prompt)
    return chain


def run_llm_chain():

    prompt = ChatPromptTemplate.from_template(
        "請幫我寫一首簡單的{song}歌。"
    )
    llm_chain = get_llm_chain(prompt)

    result = llm_chain.run("搖滾")
    print(result)

if __name__ == "__main__":
    run_llm_chain()

在這個範例中,我們就是把 llm_chain 和 prompt 這個元件組合在一起了。

Sequential chain

Chain 常見的操作是對 LLM 進行一系列的呼叫。如果想要將一次呼叫的輸出用作另一次呼叫的輸入時,Sequential chain 特別好用。

主要有兩種類型的Sequential Chain:

  • SimpleSequentialChain:這是 Sequential Chain 的最簡單形式,其中每一步都有單一的輸入/輸出,且一步的輸出是下一步的輸入。

  • SequentialChain:這是 Sequential Chain 的更通用形式,允許多個輸入與輸出。

使用 Sequential Chain,開發者可以更加容易地構建一個完整的工作流程,將多個操作串聯起來,讓資訊在整個流程中流動和傳遞。

我們馬上來做一個簡單範例,一樣在剛剛建立的 chains.py 裡操作。


def run_sequential_chain():

    llm = get_llm_model()

    prompt_one = ChatPromptTemplate.from_template(
        "請幫我寫一首簡單的{song}歌。"
    )
    chain_one = LLMChain(llm=llm, prompt=prompt_one, output_key="lyric") # 注意這裡的 output_key

    prompt_two = ChatPromptTemplate.from_template(
        "請幫我把下面這首歌翻譯成{language}:{lyric}"
    )
    chain_two = LLMChain(llm=llm, prompt=prompt_two,
                         output_key="translated_lyric")  

    prompt_three = ChatPromptTemplate.from_template(
        "請幫我把下面這首歌用一句話做摘要:{language}:"
    )
    chain_three = LLMChain(llm=llm, prompt=prompt_three,
                           output_key="summary")  
    
    overall_chain = SequentialChain(
        chains=[chain_one, chain_two, chain_three],
        input_variables=["song", "language"],
        output_variables=["lyric", "translated_lyric", "summary"],
        verbose=True
    )

    result = overall_chain({"song": "搖滾", "language": "日文"})
    print(result)

這是一個 SequentialChain,有多個輸入與輸出。我們輸入了 song 和 language 兩個參數。先是產生歌詞,然後分了兩個任務。一個任務是翻譯成我們想要的語言,另一個任務是摘要歌詞。

其他的基本 chain

其他的基本 Chain 還有下面這些,如果你的應用程式需要類似功能,可以參考與使用。

  • Router Chain:

Router Chai 提供了一種動態選擇下一個 chain 進行操作的方法,根據特定的輸入來決定。例如說我們定義了兩個 prompt,一個專注於物理,另一個專注於數學。

Router chains 主要由兩個組件組成:

RouterChain 本身:負責選擇下一個要調用的 chain 。
destination_chains:RouterChain 可以路由到的 chain 列表。

  • Transformation Chain

在處理 LLM 或資料流程時,經常需要進行一系列的資料轉換。這就是 Transformation Chain 發揮作用的地方。

Transformation Chain 是一個通用的轉換 chain ,可以幫助開發者在不更改原始資料的情況下,對其進行預處理或格式轉換,並且通常會搭配 Sequential Chain 使用。以下面這段程式碼為例,就是把輸入的文本只取前三段來使用。

def transform_func(inputs: dict):
    text = inputs["text"]
    shortened_text = "\n\n".join(text.split("\n\n")[:3])
    return {"output_text": shortened_text}


transform_chain = TransformChain(
    input_variables=["text"], output_variables=["output_text"], transform=transform_func
)

Chain 的四種型態

就像纏、練、絕、發是念能力的四種型態,在 Langchain 裡的 chain 也有四種型態:Stuff, Refine, Map reduce, 和 Map re-rank。這四種型態,原則上都可以設定到 chain 裡面,只要用 chain_type="map_rerank", 這種方式加入參數即可。

  1. Stuff

Stuff 文件 chain(stuff 有填充意思)是最直接的文件 chain 之一。它接收一串文件列表,將所有文件插入到 prompt 中,並將該提示傳遞給 LLM 進行處理。此型態非常適合於文件小且大多數呼叫只傳入少量文件的應用場景。

  1. Refine

Refine 文件 chain 透過循環輸入文件並迭代更新其答案來建立回應。對於每一個文件,它將所有非文件輸入、當前文件和最新的中間答案一起傳遞給 LLM chain 以獲得新答案。由於 Refine chain 一次只將單一文件傳遞給 LLM,所以它特別適合於需要分析超出模型上下文範圍的多份文件的任務。但此方法的明顯缺點是它會比如 Stuff 文件 chain 進行更多的 LLM 呼叫。

  1. Map reduce

Map reduce 文件 chain 首先將每個文件單獨應用於 LLM chain (即 Map 步驟),將 chain 輸出視為新文件。然後,它將所有新文件傳遞給一個單獨的組合文件 chain,以獲得單一輸出(即 Reduce 步驟)。

  1. Map re-rank

Map re-rank 文件 chain 對每個文件運行初始 prompt,該 prompt 不僅嘗試完成任務,還為其答案的確定性提供一個分數。系統將返回得分最高的回應。

轉眼間明天就是最後一天了,我們來講 Langchain 最高潮的地方:agent。


上一篇
全端 LLM 應用開發-Day28-Langchain 的 Memory
下一篇
全端 LLM 應用開發-用 Langchain 的 agent 來做更多事情(五條體產生器)
系列文
全端 LLM 應用開發(向量資料庫, Hugging Face, OpenAI, Azure ML, LangChain, FastAPI and more)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言